#!/usr/bin/env python

# Kestrel: An XMPP-based Many-Task Computing Scheduler
# Author: Lance Stout <lancestout@gmail.com>
#
# Copyright 2009-2010 Clemson University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import sys
import time
import ConfigParser
import optparse

import kestrel
import kestrel.core.xmpp as xmpp
import kestrel.lifecycles as lifecycles

from kestrel.core import Kernel
from kestrel.core.system import System
from kestrel.worker import Worker
from kestrel.manager import Manager
from kestrel.analyzer import Analyzer


def load_config(kernel, conf_file):
    conf = ConfigParser.ConfigParser()
    try:
        conf.read(os.path.expanduser(conf_file))
    except ConfigParser.MissingSectionHeaderError:
        sys.stderr.write('ERROR: Configuration file is invalid.\n')
        sys.exit()

    def handle_profile(profile):
        return profile.split()

    def handle_username(jid):
        try:
            return jid[0:jid.index('@')]
        except:
            return jid

    temp_map = [
        ('XMPP/client/username', ('XMPP', 'jid'), handle_username),
        ('XMPP/component/username', ('XMPP', 'jid'), None),
        ('XMPP/client/password', ('XMPP', 'password'), None),
        ('XMPP/component/secret', ('XMPP', 'password'), None),
        ('XMPP/client/server', ('XMPP', 'server'), None),
        ('XMPP/component/server', ('XMPP', 'server'), None),
        ('XMPP/component/port', ('XMPP', 'port'), None),
        ('worker/manager/id', ('worker', 'manager'), None),
        ('worker/profile/provides', ('worker', 'profile'), handle_profile)]

    for item in temp_map:
        path = item[0]
        section, option = item[1]
        handler = item[2]

        try:
            setting = conf.get(section, option)
            if handler is not None:
                setting = handler(setting)
            kernel.set_config(path, setting)
        except ConfigParser.NoSectionError:
            pass
        except ConfigParser.NoOptionError:
            pass


def load_worker(kernel, *args):
    kernel.set_config('kernel/lifecycles/worker', lifecycles.Worker)
    kernel.set_config('kernel/roles/worker', Worker())
    kernel.set_config('kernel/roles/system', System())


def load_manager(kernel, *args):
    kernel.set_config('kernel/lifecycles/manager', lifecycles.Manager)
    kernel.set_config('kernel/roles/manager', Manager())
    kernel.set_config('kernel/roles/system', System())
    kernel.set_config('system/XMPP', xmpp.Component)


def load_user(kernel, *args):
    pass


def load_analyzer(kernel, *args):
    kernel.set_config('kernel/lifecycles/analyzer', lifecycles.Analyzer)
    kernel.set_config('kernel/roles/analyzer', Analyzer())
    kernel.set_config('analyzer/log', args[1])


def main():
    opts = optparse.OptionParser()
    opts.usage = "Usage: %prog [options] worker|manager|user|analyzer"
    opts.version = '%%prog %s' % kestrel.__version__
    opts.add_option('-c', '--conf', dest='config',
                    metavar='FILE',
                    default='~/.kestrelrc',
                    help=('Alternate location for config file. '
                          'Default: %default'))
    (options, args) = opts.parse_args()

    if len(args) < 1:
        opts.print_help()
        return

    kernel = Kernel()
    load_config(kernel, options.config)

    roles = {'worker': load_worker,
             'manager': load_manager,
             'user': load_user,
             'analyzer': load_analyzer}

    setup = roles.get(args[0], load_worker)
    setup(kernel, *args)

    kernel.start(args[0])
    try:
        while True:
            time.sleep(10)
    except KeyboardInterrupt:
        kernel.stop()
        return

if __name__ == '__main__':
    main()
